import 'dart:convert';

import 'package:http/http.dart' as http;
import 'package:meta/meta.dart';
import 'package:rxdart/rxdart.dart';

class ResponseModel<T> {
  String msg;
  int code;
  T data;

  ResponseModel(Map res) {
    msg = res['msg'];
    code = res['code'];
  }
}

typedef DataFactory<T> = T Function(dynamic res);

typedef ResponseHandler = void Function(http.Response response);
typedef StatusErrorHandler = void Function(String msg, int status);

class HttpHelper {
  bool isMock = false;
  Map<Uri, String> mockDatas = {};

  Stream<T> fetch<T>({
    @required Uri uri,
    @required DataFactory<T> fac,
    ResponseHandler errorHandler,
    StatusErrorHandler statusErrorHandler,
  }) {
    Stream<String> textStream;
    if (isMock) {
      textStream = Stream.value(mockDatas[uri]).delay(
        Duration(milliseconds: 1000),
      );
    } else {
      final response = http.get(uri);
      textStream = Stream.fromFuture(response).flatMap((v) {
        if (v.statusCode != 200) {
          if (errorHandler != null) {
            errorHandler(v);
          } else {
            print('状态码错误: ${v.statusCode}');
          }
          return Stream.empty();
        }
        return Stream.value(v.body);
      });
    }

    return textStream.flatMap((v) {
      final res = json.decode(v);
      final response = ResponseModel<T>(res);

      if (response.code != 200) {
        if (statusErrorHandler != null) {
          statusErrorHandler(
            response.msg,
            response.code,
          );
        } else {
          print(response.msg);
        }
        return Stream.empty();
      }

      response.data = fac(res['data']);

      return Stream.value(response.data);
    });
  }
}
